<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="shortcut icon" type="image/ico" href="/samwaf_captcha/favicon.ico" />
    <link rel="stylesheet" type="text/css" href="/samwaf_captcha/css/gocaptcha.global.css">
    <link rel="stylesheet" type="text/css" href="/samwaf_captcha/css/toastify.css">
    <title>进行验证</title>
    <style>
        html, body {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            color: #3C3C3C;
            background: #EBF3FB;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .example {
            padding: 40px 0;
        }

        .box{
            margin: 30px;
        }
    </style>
</head>
<body>
<div class="example">
    <div class="box" id="click-wrap"></div> 
</div>
<!-- GoCaptcha -->
<script type="text/javascript" src="/samwaf_captcha/js/gocaptcha.global.js"></script>
<!-- Http Request -->
<script src="/samwaf_captcha/js/axios.js"></script>
<!-- Request parameter serialization-->
<script src="/samwaf_captcha/js/qs.js"></script>
<!-- Toast Tip -->
<script src="/samwaf_captcha/js/toastify.js"></script>

<script type="text/javascript">
// 机器人检测模块
(function() {
    // 初始化检测变量
    let mouseMovements = 0;
    let lastMouseX = 0;
    let lastMouseY = 0;
    let mouseTrack = [];
    let startTime = Date.now();
    let botScore = 0;
    let isBotDetected = false;
    let clickTimes = [];
    
    // 检测自动化工具和模拟器
    function detectAutomation() {
        // 检测常见的自动化工具特征
        const automationFlags = [
            !!window.document.documentElement.getAttribute('selenium'),
            !!window.document.documentElement.getAttribute('webdriver'),
            !!window._phantom,
            !!window.callPhantom,
            !!window.__nightmare,
            !!window.domAutomation,
            !!window.domAutomationController,
            navigator.webdriver === true,
            navigator.userAgent.indexOf('Selenium') !== -1,
            navigator.userAgent.indexOf('PhantomJS') !== -1,
            navigator.userAgent.indexOf('Headless') !== -1
        ];
        
        // 检测到任何自动化工具标志
        automationFlags.forEach(flag => {
            if (flag) botScore += 20;
        });
        
        // 检测异常的浏览器特征
        if (navigator.hardwareConcurrency < 2) botScore += 10;
        if (navigator.plugins.length === 0) botScore += 10;
        if (navigator.languages === undefined) botScore += 10;
        
        // 检测Canvas指纹
        try {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            ctx.textBaseline = "top";
            ctx.font = "14px 'Arial'";
            ctx.fillStyle = "#f60";
            ctx.fillRect(125, 1, 62, 20);
            ctx.fillStyle = "#069";
            ctx.fillText("SamWaf防护", 2, 15);
            ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
            ctx.fillText("SamWaf防护", 4, 17);
            
            const dataURL = canvas.toDataURL();
            if (dataURL === 'data:,') botScore += 20; // 空数据URL通常表示headless浏览器
        } catch(e) {
            botScore += 15; // Canvas操作异常
        }
        
        return botScore >= 30;
    }
    
    // 监听鼠标移动
    document.addEventListener('mousemove', function(e) {
        mouseMovements++;
        
        // 记录鼠标轨迹
        if (mouseTrack.length < 100) {
            mouseTrack.push({
                x: e.clientX,
                y: e.clientY,
                time: Date.now() - startTime
            });
        }
        
        // 检测鼠标移动是否过于机械
        if (lastMouseX !== 0 && lastMouseY !== 0) {
            const dx = e.clientX - lastMouseX;
            const dy = e.clientY - lastMouseY;
            
            // 检测直线移动
            if (dx === 0 || dy === 0) {
                botScore += 1;
            }
            
            // 检测等距移动
            if (mouseTrack.length > 3) {
                const last = mouseTrack[mouseTrack.length - 1];
                const prev = mouseTrack[mouseTrack.length - 2];
                const prevPrev = mouseTrack[mouseTrack.length - 3];
                
                const dist1 = Math.sqrt(Math.pow(last.x - prev.x, 2) + Math.pow(last.y - prev.y, 2));
                const dist2 = Math.sqrt(Math.pow(prev.x - prevPrev.x, 2) + Math.pow(prev.y - prevPrev.y, 2));
                
                if (Math.abs(dist1 - dist2) < 0.5) {
                    botScore += 1;
                }
            }
        }
        
        lastMouseX = e.clientX;
        lastMouseY = e.clientY;
    });
    
    // 监听点击事件
    document.addEventListener('click', function(e) {
        clickTimes.push(Date.now());
        
        // 检测点击间隔是否过于规律
        if (clickTimes.length >= 3) {
            const interval1 = clickTimes[clickTimes.length - 1] - clickTimes[clickTimes.length - 2];
            const interval2 = clickTimes[clickTimes.length - 2] - clickTimes[clickTimes.length - 3];
            
            if (Math.abs(interval1 - interval2) < 50) {
                botScore += 5; // 点击间隔过于规律
            }
        }
        
        // 检测点击位置是否过于精确
        if (e.clientX % 1 === 0 && e.clientY % 1 === 0) {
            botScore += 2; // 精确到整数像素的点击
        }
    });
    
    // 定期检查机器人特征
    setInterval(function() {
        // 检测鼠标移动是否太少
        const timeElapsed = (Date.now() - startTime) / 1000;
        if (timeElapsed > 3 && mouseMovements < 5) {
            botScore += 10; // 3秒内鼠标移动次数少于5次
        }
        
        // 检测自动化工具
        if (detectAutomation()) {
            isBotDetected = true;
        }
        
        // 如果机器人分数过高，标记为机器人
        if (botScore >= 30) {
            isBotDetected = true;
        }
        
        // 如果检测到机器人，发送到服务器
        if (isBotDetected) {
            // 向服务器报告可能的机器人行为
            axios({
                method: 'post',
                url: '/samwaf_captcha/report_bot',
                data: Qs.stringify({
                    score: botScore,
                    userAgent: navigator.userAgent,
                    screenInfo: `${window.screen.width}x${window.screen.height}`,
                    timestamp: Date.now()
                })
            }).catch(e => {
                // 静默处理错误
            });
            
            // 增加验证难度或显示额外验证
            const captchaEl = document.getElementById('click-wrap');
            if (captchaEl) {
                // 可以在这里修改验证码的难度或行为
            }
        }
    }, 2000);
})();

axios.defaults.baseURL = '/';

function toastSuccess(msg) {
    Toastify({
        text: msg,
        duration: 1000,
        newWindow: true,
        gravity: "top",
        position: "center",
        style: {
            background: "#f0f9eb",
            border: "1px solid #dcf9cc",
            color: "#5eaa2f",
            borderRadius: "6px",
            boxShadow: "1px 1px 10px #e0e0e0",
            padding: "8px 20px"
        },
    }).showToast();
}

function toastError(msg) {
    Toastify({
        text: msg,
        duration: 1000,
        newWindow: true,
        gravity: "top",
        position: "center",
        style: {
            background: "#fef0f0",
            border: "1px solid #fcd6d6",
            color: "#ed4630",
            borderRadius: "6px",
            boxShadow: "1px 1px 10px #e0e0e0",
            padding: "8px 20px"
        },
    }).showToast();
}


// Click 
;(function (goCaptcha){
    const getDataApi = "/samwaf_captcha/click_basic";
    const checkDataApi = "/samwaf_captcha/verify";

    const el = document.getElementById("click-wrap");
    const capt = new goCaptcha.Click({
        width: 300,
        height: 220,
        // iconSize: 30,
    });

    var captKey = ''

    capt.mount(el)

    capt.setEvents({
        click(x,  y) { 
        },
        confirm(dots, reset) {
            // 添加机器人检测数据
            const botData = {
                mouseTrack: window.mouseTrack || [],
                timing: Date.now(),
                pattern: dots.map(d => ({ x: d.x, y: d.y }))
            };
            
            confirmEvent(dots, botData)
        },
        refresh() {
            capt.clear()
            requestCaptchaData()
        },
        close() { 
        }
    })

    const requestCaptchaData = function() {
        capt.clear()
        captKey = ''
        axios({
            method: 'get',
            url: getDataApi,
        }).then(function(response){
            const data = response.data || {};
            if (data && (data['code'] || 0) === 0) {
                capt.setData({
                    image: data['image_base64'] || '',
                    thumb: data['thumb_base64'] || '',
                })
                captKey = data['captcha_key'] || ''
            } else {
                toastError(`获取数据失败`)
            }
        }).catch((e)=>{
            console.warn(e)
        })
    }

    const confirmEvent = function (dots, botData) {
        const dotArr = []
        for (let i = 0; i < dots.length; i++) {
            const dot = dots[i]
            dotArr.push(dot.x, dot.y)
        }

        axios({
            method: 'post',
            url: checkDataApi,
            data: Qs.stringify({
                dots: dotArr.join(','),
                key: captKey || '',
                botCheck: JSON.stringify(botData || {})
            }),
        }).then(function (response){
            const data = response.data || {};
            if (data && (data['code'] || 0) === 0) {
                // 隐藏验证码元素
                document.getElementById("click-wrap").style.display = "none";
                // 添加成功提示
                const successEl = document.createElement("div");
                successEl.className = "box";
                successEl.innerHTML = "<h3 style='color: #5eaa2f; text-align: center;'>验证成功，页面即将刷新...</h3>";
                document.querySelector(".example").appendChild(successEl);
                
                setTimeout(() => {
                    window.location.reload();
                }, 2000);
            } else {
                toastError(`校验失败`)
                
                setTimeout(() => {
                    requestCaptchaData()
                }, 500)
            }
        }).catch((e)=>{
            console.warn(e)
            setTimeout(() => {
                requestCaptchaData()
            }, 500)
        })
    }

    requestCaptchaData()
})(window.GoCaptcha || {}) 

</script>
</body>
</html>
